#include <sstream>
#include <algorithm>
#include <odb/database.hxx>
#include <odb/mysql/database.hxx>

#include "message-odb.hxx"
#include "logger.hpp"

namespace im
{
    class MessageTable
    {
    public:
        using ptr = std::shared_ptr<MessageTable>;
        MessageTable(const std::shared_ptr<odb::database>& db):_db(db){}

        bool insert(Message& msg){
            try{
                odb::transaction t(_db->begin());
                _db->persist(msg);
                t.commit();
            } catch(const std::exception& e) {
                LOG_CRITICAL("新增消息失败 {}:{}！", msg.message_id(),e.what());
                return false;
            }
            return true;
        }

        bool remove(const std::string& ssid){
            try{
                odb::transaction t(_db->begin());
                _db->erase_query<Message>(odb::query<Message>::session_id == ssid);
                t.commit();
            }
            catch(const std::exception& e){
                LOG_CRITICAL("删除会话所有消息失败 {}:{}！", ssid, e.what());
                return false;
            }
            return true;
        }

        std::vector<Message> recent(const std::string& ssid, int limit){
            std::vector<Message> msg_list;
            try{
                odb::transaction t(_db->begin());
                std::stringstream cond;
                cond << "session_id='" << ssid << "' ";
                cond << "order by create_time desc limit " << limit;
                odb::result<Message> res(_db->query<Message>(cond.str()));
                for(auto& msg : res){
                    msg_list.push_back(msg);
                }
                std::reverse(msg_list.begin(), msg_list.end());
                t.commit();
            }
            catch(const std::exception& e) {
                LOG_CRITICAL("获取最近{}消息失败:{}-{}！", limit, e.what(), ssid);
            }
            return msg_list;
        }

        std::vector<Message> range(const std::string& ssid, boost::posix_time::ptime &stime,  boost::posix_time::ptime &etime){
            std::vector<Message> msg_list;
            try{
                odb::transaction t(_db->begin());
                typedef odb::query<Message> query;
                odb::result<Message> res(_db->query<Message>(query::session_id == ssid
                                                            && query::create_time >= stime
                                                            && query::create_time <= etime));
                for(auto& msg : res){
                    msg_list.push_back(msg);
                }
                t.commit();
            } catch (const std::exception& e) {
                LOG_CRITICAL("获取{}~{} 消息失败:{}-{}！", 
                    boost::posix_time::to_simple_string(stime), 
                    boost::posix_time::to_simple_string(etime),
                    e.what(), ssid);
            }
            return msg_list;
        }

    private:
        std::shared_ptr<odb::database> _db;
    };

    
} // namespace im
